import os
import sys

script_path = os.path.abspath(__file__)
script_dir = os.path.dirname(script_path)
sys.path.insert(0, script_dir)

from typing import Any, Dict, Literal, List, NewType
from pygame.sprite import AbstractGroup, Sprite
from pygame import event, image, Surface, transform
from abc import ABC, abstractmethod
from obj.baseClass.bullet import *
from obj.baseClass.amount import *
from obj.baseClass.zombie import *
from obj.baseClass.other import *
from obj.baseClass.card import *
from obj.baseClass.plant import *
from obj.bullet import *
from obj.zombie import *
from obj.plant import *
from role.obj.scene import *
from obj.card import *
from obj.scene import *


# ---------------------------------- 精灵组模板基类 --------------------------------- #
class sprite_group(
    ABC,
    Sprite,
):
    """精灵组模板基类"""

    def __init__(self, *sprites) -> None:
        super().__init__(*sprites)

    @abstractmethod
    def update(self, *args: Any, **kwargs: Any) -> None:
        """更新"""
        pass

    @abstractmethod
    def draw(self, surface: Surface) -> None:
        """绘制"""
        pass

    @abstractmethod
    def add(self, *sprite: Sprite) -> None:
        """添加"""
        pass

    @abstractmethod
    def remove(self, *sprite: Sprite) -> None:
        """移除"""
        pass

    @abstractmethod
    def mouse_event(self, event: event.Event) -> None:
        """鼠标点击"""
        pass


# ---------------------------------------------------------------------------- #


# ----------------------------------- 精灵类组 ----------------------------------- #

groupsT = NewType(
    "groupsT", Dict[Literal["zombieG", "bulletG", "plantG", "cardG"], sprite_group]
)


# region ✨植物卡片精灵组
class _card_sprite_group(sprite_group):
    def __init__(self, *sprites) -> None:
        super().__init__(*sprites)
        self.image = image.load("./PVZ素材/小部分组件/菜单栏/植物商店.png")
        h = 60
        self.image = transform.scale(
            self.image, (self.image.get_width() * (h / self.image.get_height()), h)
        )
        self.rect = self.image.get_rect()

        self.group = AbstractGroup()
        self.groups_list: sprite_group
        self.sumGroup: groupsT
        self.nums = 0
        self.max = 12
        self.margin_left = 90
        self.margin_top = 5

    def update(self, *args: Any, **kwargs: Any) -> None:
        self.group.update(
            margin_left=self.margin_left, margin_top=self.margin_top, *args, **kwargs
        )
        self.group.draw(self.image)

    def add(self, *cards: Card) -> None:
        """添加植物卡"""
        if self.nums < self.max:
            for card in cards:
                h = self.image.get_height() - self.image.get_height() * 0.1

                # 精灵图片更新
                card.image = transform.scale(
                    card.image, (card.rect.width * (h / card.rect.height), h)
                )
                card.rect = card.image.get_rect()

                # 垂直居中
                card.rect.centery = self.image.get_height() * 0.04

                # 蒙版更新
                card.img_copy = card.image.copy()
                card.img_copy_rect = card.img_copy.get_rect()

                card.index = self.nums
                card.rect.x = self.nums * card.rect.width + self.margin_left
                card.rect.y = self.margin_top

                self.group.add(card)
                self.nums = self.nums + 1

    def remove(self, *cards: Card):
        """移除"""
        for card in cards:
            self.group.remove(card)

    def draw(self, surface: Surface):
        """绘制"""
        surface.blit(self.image, self.image.get_rect())

    def mouse_event(self, event: event.Event) -> None:
        """鼠标事件"""
        for sprite in self.sprites():
            sprite.mouse_event(event)


# region ✨植物精灵组
class _plant_sprite_group(sprite_group):
    """植物精灵组"""

    def __init__(self, *sprites) -> None:
        super().__init__(*sprites)
        self.group = AbstractGroup()
        self.sumGroup: Dict[
            Literal["zombieG", "bulletG", "plantG", "cardG"], sprite_group
        ]

    def add(self, *sprite):
        self.group.add(*sprite)

    def remove(self, *sprite: Bullet):
        self.group.remove(*sprite)

    def draw(self, surface: Surface):
        self.group.draw(surface)

    def update(self):
        self.group.update()

    def mouse_event(self, event: event.Event) -> None:
        pass


# region ✨僵尸精灵组
class _zombie_sprite_group(sprite_group):
    """僵尸精灵组"""

    def __init__(self, *sprites) -> None:
        super().__init__(*sprites)
        self.group = AbstractGroup()
        self.sumGroup: Dict[
            Literal["zombieG", "bulletG", "plantG", "cardG"], sprite_group
        ]

    def add(self, *sprite: Zombie):
        self.group.add(*sprite)

    def remove(self, *sprite: Zombie):
        self.group.remove(*sprite)

    def draw(self, surface: Surface):
        self.group.draw(surface)

    def update(self):
        sprZoms: List[Zombie] = self.group.sprites()
        sprPlants: List[Plant] = self.sumGroup["plantG"].group.sprites()
        for _zombie_ in sprZoms:
            if _zombie_.status != 3:
                if _zombie_.BVolume <= 0:
                    if _zombie_.status != 3:
                        _zombie_.status = 3
                    continue
                for _plant_ in sprPlants:
                    if _zombie_.rect.colliderect(_plant_.rect):
                        if _zombie_.status != 2:
                            _zombie_.status = 2
                        _plant_ -= Life(_zombie_.Damage.value)
            _zombie_.update()

    def mouse_event(self, event: event.Event) -> None:
        pass


# region ✨子弹精灵组
class _bullet_sprite_group(sprite_group):
    """子弹精灵组"""

    def __init__(self, *sprites) -> None:
        super().__init__(*sprites)
        self.group = AbstractGroup()
        self.sumGroup: Dict[
            Literal["zombieG", "bulletG", "plantG", "cardG"], sprite_group
        ]

    def add(self, *sprite: Bullet):
        self.group.add(*sprite)

    def remove(self, *sprite: Bullet):
        self.group.remove(*sprite)

    def draw(self, surface: Surface):
        self.group.draw(surface)

    def update(self):
        self.group.update()
        sprZoms: List[Zombie] = self.sumGroup["zombieG"].group.sprites()
        sprBuls: List[Bullet] = self.group.sprites()
        for zombie_ in sprZoms:
            if zombie_.status == 3:
                continue
            for bullet_ in sprBuls:
                if bullet_.rect.colliderect(zombie_.rect):
                    self.group.remove(bullet_)
                    zombie_.BVolume -= bullet_.damage.value

    def mouse_event(self, event: event.Event):
        pass


# ---------------------------------------------------------------------------- #


# ----------------------------------- 类组控制器 ---------------------------------- #
# region ✨精灵组集合
class spriteGroup(AbstractGroup):
    """总精灵组"""

    def __init__(self, *sprites) -> None:
        """初始化"""
        super().__init__(*sprites)
        self._groups: Dict[
            Literal["zombieG", "bulletG", "plantG", "cardG"], sprite_group
        ] = {}
        self.zombie = _zombie_sprite_group()
        self.bullet = _bullet_sprite_group()
        self.plant = _plant_sprite_group()
        self.card = _card_sprite_group()
        self._groups["zombieG"] = self.zombie
        self._groups["bulletG"] = self.bullet
        self._groups["plantG"] = self.plant
        self._groups["cardG"] = self.card
        self.scene = DawnDay()

        for group in self._groups.values():
            group.sumGroup = self._groups

    def __identify(self, sprite: Sprite) -> sprite_group:
        """识别"""
        if isinstance(sprite, Zombie):
            return self.zombie
        elif isinstance(sprite, Card):
            return self.card
        elif isinstance(sprite, Plant):
            return self.plant
        elif isinstance(sprite, Bullet):
            return self.bullet
        else:
            raise TypeError("sprite must be a subclass of Sprite")

    def update(self, *args, **kwargs):
        """更新"""

        for groups in self._groups.values():
            groups.update(*args, **kwargs)

    def draw(self, surface: Surface):
        """绘制"""
        self.scene.draw(surface)
        for groups in self._groups.values():
            # ----------------------------------- 跟踪红框 ----------------------------------- #
            for group in groups.group.sprites():
                pygame.draw.rect(surface, (255, 0, 0), group.rect, 2)
            # ---------------------------------------------------------------------------- #
            groups.draw(surface)

    def add(self, *sprite: Sprite):
        """添加"""
        for sprite_ in sprite:
            self.__identify(sprite_).add(sprite_)

    def remove(self, *sprite: Sprite):
        """移除"""
        for sprite_ in sprite:
            self.__identify(sprite_).remove(sprite_)


# ---------------------------------------------------------------------------- #
